// ------------------------------------------------------------------------------
// 
// Copyright (c) 2008 Swampware, Inc.
// 
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// 
// ------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;

namespace Bamboo.Parsing.Generators.CSharp
{
	public class GeneratorGenerator
	{

		public static void Generate(string name, string nspace, Bamboo.Parsing.Grammars.Grammar grammar, System.IO.TextWriter writer)
		{
			writer.WriteLine("//");
			writer.WriteLine("// AUTOGENERATED " + System.DateTime.Now + "");
			writer.WriteLine("//");
			writer.WriteLine("using System;");
			writer.WriteLine("");
			writer.WriteLine("namespace " + nspace + "");
			writer.WriteLine("{");
			writer.WriteLine("	public class " + name + "Generator");
			writer.WriteLine("	{");
			writer.WriteLine("");
			writer.WriteLine("		public " + name + "Generator()");
			writer.WriteLine("		{");
			writer.WriteLine("		}");
			writer.WriteLine("");
			writer.WriteLine("		public void Generate(" + name + "Node node, System.IO.TextWriter writer)");
			writer.WriteLine("		{");
			writer.WriteLine("			bool writeWhitespace = false;");
			writer.WriteLine("");
			writer.WriteLine("			Generate(node, writer, ref writeWhitespace);");
			writer.WriteLine("		}");
			writer.WriteLine("");
			writer.WriteLine("		private void Generate(" + name + "Node node, System.IO.TextWriter writer, ref bool writeWhitespace)");
			writer.WriteLine("		{");
			writer.WriteLine("			switch(node.Type)");
			writer.WriteLine("			{");
			foreach (string nonterminal in grammar.Nonterminals)
			{
				writer.WriteLine("				case " + name + "NodeType." + nonterminal + ":");
				writer.WriteLine("					{");
				writer.WriteLine("						for(int i = 0; i < node.Nodes.Count; i++)");
				writer.WriteLine("						{");
				writer.WriteLine("							Generate(node.Nodes[i], writer, ref writeWhitespace);");
				writer.WriteLine("						}");
				writer.WriteLine("						break;");
				writer.WriteLine("					}");
			}
			foreach (string terminal in grammar.Terminals)
			{
				writer.WriteLine("				case " + name + "NodeType." + terminal + ":");
				writer.WriteLine("					{");
				writer.WriteLine("						if(writeWhitespace)");
				writer.WriteLine("						{");
				writer.WriteLine("							writer.Write(\" \");");
				writer.WriteLine("						}");
				writer.WriteLine("						writer.Write(node.Value);");
				writer.WriteLine("						writeWhitespace = true;");
				writer.WriteLine("						break;");
				writer.WriteLine("					}");
			}
			writer.WriteLine("				default:");
			writer.WriteLine("					{");
			writer.WriteLine("						throw new System.Exception(\"Invalid node type.\");");
			writer.WriteLine("					}");
			writer.WriteLine("			}");
			writer.WriteLine("		}");
			writer.WriteLine("");
			writer.WriteLine("	}");
			writer.WriteLine("}");
		}

		private static List<Bamboo.Parsing.Grammars.Production> GetProductions(string nonterminal, Bamboo.Parsing.Grammars.Grammar grammar)
		{
			List<Bamboo.Parsing.Grammars.Production> productions = new List<Bamboo.Parsing.Grammars.Production>();
			foreach (Bamboo.Parsing.Grammars.Production production in grammar.Productions)
			{
				if (production.Nonterminal.Equals(nonterminal))
				{
					productions.Add(production);
				}
			}
			return productions;
		}

		private GeneratorGenerator()
		{
		}

	}
}
